/*
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "graph.h"

GPlot::GPlot(bool constraint, int steps, QVector<Solution>& results, bool den,int minden, int maxden,
             bool tigh, int mintight, int maxtight, int cpuMax, bool cutsjumps, int maxcut, int maxjump,
             QWidget *parent):
QwtPlot( parent )
{
    // panning with the left mouse button
    (void) new QwtPlotPanner( canvas() );

    // zoom in/out with the wheel
    (void) new QwtPlotMagnifier( canvas() );

    setAutoFillBackground( true );
    setPalette( QPalette( QColor( 165, 193, 228 ) ) );
    updateGradient();
    if(!cutsjumps){
        if(constraint)
            setTitle("Cpu Usage With Constraints Propagation " );
        else
            setTitle("Cpu Usage Without Constraints Propagation " );
        insertLegend(new QwtLegend(), QwtPlot::RightLegend);

        setAxisTitle(yLeft, "Cpu Time (ms)");
        setAxisScale(yLeft, 0, cpuMax);
    }else{
        if(constraint)
            setTitle("Cuts and Jumps With Constraints Propagation " );
        else
            setTitle("Cuts and Jumps Without Constraints Propagation " );

        insertLegend(new QwtLegend(), QwtPlot::RightLegend);
        setAxisTitle(yLeft, "avg jumps (#)");
        setAxisScale(yLeft, 0, maxjump);
        //enableAxis(yLeft, true);
        setAxisTitle(yRight, "avg cuts (#)");
        setAxisScale(yRight, 0, maxcut);
        enableAxis(yRight, true);
    }

    // axes
    setAxisTitle(xBottom,(tigh?"Tightness":(den?"Density":"Iteration")));
    if(tigh){
        setAxisScale(xBottom, mintight, maxtight);
    }
    else if (den){
        setAxisScale(xBottom, minden, maxden);
    }else{
        setAxisScale(xBottom, 0.0, results.size());
    }

    // canvas
    canvas()->setLineWidth( 1 );
    canvas()->setFrameStyle( QFrame::Box | QFrame::Plain );
    canvas()->setBorderRadius( 15 );

    QPalette canvasPalette( Qt::white );
    canvasPalette.setColor( QPalette::Foreground, QColor( 133, 190, 232 ) );
    canvas()->setPalette( canvasPalette );

    int min;
    if(tigh){
        min = mintight;
    }
    else if (den){
        min = minden;
    }else{
        min = 0;
    }

    if(!cutsjumps)
        populate(results,den,tigh,steps,min);
    else
        populate_cj(results,den,tigh,steps,min);
}


void GPlot::populate(QVector<Solution>& results, bool den, bool tigh, int steps,int min)
{
    // Insert new curves
    QwtPlotCurve *line = new QwtPlotCurve("time");
    line->setRenderHint(QwtPlotItem::RenderAntialiased);
    line->setLegendAttribute(QwtPlotCurve::LegendShowLine, true);
    line->setPen(QPen(Qt::red));
    line->attach(this);

    double * xval = new double[results.size()];
    double * yval = new double[results.size()];
    for(int k = 0; k < results.size(); k++){
        if(den)
            xval[k] = steps*k+min;
        else if(tigh)
            xval[k] = steps*k+min;
        else
            xval[k] = k;

        yval[k] = results[k].getCpuTime();
    }

    line->setRawSamples(xval,yval,results.size());

    // Insert markers

    //  ...a horizontal line at y = 0...
    QwtPlotMarker *mY = new QwtPlotMarker();
    mY->setLabel(QString::fromLatin1("y = 0"));
    mY->setLabelAlignment(Qt::AlignRight|Qt::AlignTop);
    mY->setLineStyle(QwtPlotMarker::HLine);
    mY->setYValue(0.0);
    mY->attach(this);

    //  ...a vertical line at x = 0
    QwtPlotMarker *mX = new QwtPlotMarker();
    mX->setLabel(QString::fromLatin1("x = 0"));
    mX->setLabelAlignment(Qt::AlignLeft | Qt::AlignBottom);
    mX->setLabelOrientation(Qt::Vertical);
    mX->setLineStyle(QwtPlotMarker::VLine);
    mX->setLinePen(QPen(Qt::black, 0, Qt::DashDotLine));
    mX->setXValue(0.0);
    mX->attach(this);
}

void GPlot::populate_cj(QVector<Solution>& results, bool den, bool tigh, int steps, int min)
{
    // Insert new curves
    QwtPlotCurve *jump = new QwtPlotCurve("jumps");
    jump->setRenderHint(QwtPlotItem::RenderAntialiased);
    jump->setLegendAttribute(QwtPlotCurve::LegendShowLine, true);
    jump->setPen(QPen(Qt::red));
    jump->attach(this);

    jump->setAxes(xBottom,yLeft);

    QwtPlotCurve *cut = new QwtPlotCurve("cuts");
    cut->setRenderHint(QwtPlotItem::RenderAntialiased);
    cut->setLegendAttribute(QwtPlotCurve::LegendShowLine, true);
    cut->setPen(QPen(Qt::blue));
    cut->attach(this);

    cut->setAxes(xBottom,yRight);

    double * xval = new double[results.size()];
    double * yval = new double[results.size()];
    for(int k = 0; k < results.size(); k++){
        if(den)
            xval[k] = steps*k+min;
        else if(tigh)
            xval[k] = steps*k+min;
        else
            xval[k] = k;

        yval[k] = results[k].getJumps();
    }

    jump->setRawSamples(xval,yval,results.size());

    xval = new double[results.size()];
    yval = new double[results.size()];
    for(int k = 0; k < results.size(); k++){
        if(den)
            xval[k] = steps*k+min;
        else if(tigh)
            xval[k] = steps*k+min;
        else
            xval[k] = k;

        yval[k] = results[k].getCuts();
    }

    cut->setRawSamples(xval,yval,results.size());

    // Insert markers

    //  ...a horizontal line at y = 0...
    QwtPlotMarker *mY = new QwtPlotMarker();
    mY->setLabel(QString::fromLatin1("y = 0"));
    mY->setLabelAlignment(Qt::AlignRight|Qt::AlignTop);
    mY->setLineStyle(QwtPlotMarker::HLine);
    mY->setYValue(0.0);
    mY->attach(this);

    //  ...a vertical line at x = 0
    QwtPlotMarker *mX = new QwtPlotMarker();
    mX->setLabel(QString::fromLatin1("x = 0"));
    mX->setLabelAlignment(Qt::AlignLeft | Qt::AlignBottom);
    mX->setLabelOrientation(Qt::Vertical);
    mX->setLineStyle(QwtPlotMarker::VLine);
    mX->setLinePen(QPen(Qt::black, 0, Qt::DashDotLine));
    mX->setXValue(0.0);
    mX->attach(this);
}

void GPlot::updateGradient()
{
    QPalette pal = palette();

    const QColor buttonColor = pal.color( QPalette::Button );

#ifdef Q_WS_X11
    // Qt 4.7.1: QGradient::StretchToDeviceMode is buggy on X11

    QLinearGradient gradient( rect().topLeft(), rect().bottomLeft() );
    gradient.setColorAt( 0.0, Qt::white );
    gradient.setColorAt( 0.7, buttonColor );
    gradient.setColorAt( 1.0, buttonColor );
#else
    QLinearGradient gradient( 0, 0, 0, 1 );
    gradient.setCoordinateMode( QGradient::StretchToDeviceMode );
    gradient.setColorAt( 0.0, Qt::white );
    gradient.setColorAt( 0.7, buttonColor );
    gradient.setColorAt( 1.0, buttonColor );
#endif

    pal.setBrush( QPalette::Window, gradient );
    setPalette( pal );
}

void GPlot::resizeEvent( QResizeEvent *event )
{
    QwtPlot::resizeEvent( event );
#ifdef Q_WS_X11
    updateGradient();
#endif
}

